package cn.nexd.map;

import android.app.Activity;
import android.content.Context;
import android.graphics.PointF;
import android.text.TextUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.nexd.map.coreLocator.coreAlgorithm;
import cn.nexd.map.http.AuthFailureError;
import cn.nexd.map.http.DefaultRetryPolicy;
import cn.nexd.map.http.NetworkResponse;
import cn.nexd.map.http.Request;
import cn.nexd.map.http.RequestQueue;
import cn.nexd.map.http.Response;
import cn.nexd.map.http.VolleyError;
import cn.nexd.map.http.toolbox.HttpHeaderParser;
import cn.nexd.map.http.toolbox.StringRequest;
import cn.nexd.map.http.toolbox.Volley;
import cn.nexd.map.location.collector.Collector;
import cn.nexd.map.location.collector.CollectorConfig;
import cn.nexd.map.location.collector.bean.BasebandDataResult;
import cn.nexd.map.location.collector.bean.BluetoothDataResult;
import cn.nexd.map.location.collector.bean.WifiDataResult;
import cn.nexd.map.location.collector.listener.BasebandCollectorResultListener;
import cn.nexd.map.location.collector.listener.BluetoothCollrctorResultListener;
import cn.nexd.map.location.collector.listener.WifiCollectorResultListener;
import cn.nexd.map.location.collector.util.NexdCollectionAgent;
import cn.nexd.map.location.task.core.NexdCollectionAsyncTask;
import cn.nexd.map.location.task.core.TaskExecutor;
import cn.nexd.map.location.utils.Log;
import cn.nexd.map.rendering.POIData;
import cn.nexd.map.rendering.PlanningLiesmanData;
import cn.nexd.map.rendering.PointData;
import cn.nexd.map.rendering.core.componet.SVGMapView;
import cn.nexd.map.rendering.core.componet.data.Floors;
import cn.nexd.map.rendering.core.componet.data.FloorsFeature;
import cn.nexd.map.rendering.core.helper.FloorsUtils;
import cn.nexd.map.rendering.core.helper.JsonParseUtil;
import cn.nexd.map.rendering.core.helper.WifiSignalHelper;
import cn.nexd.map.utils.BitmapUtils;

/**
 * 对外提供服务的类。该类主要完成地图的显示、定位服务。并在此类中进行相应的业务分发。
 * Created by codingfish on 15/8/11.
 */
public class NexdLocationAgent {


    private Context context;
    private NexdLocationListener locationListener;
    private NexdLocationSignalListener nexdLocationSignalListener;
    private CollectorConfig.Builder collectorConfig;
    private NexdCollectionAgent collectionAgent;
    private int planningLinesmanMode = PLANNING_LINESMANMODE_DEFAUIT;
    private int timeout = 6;
    private int retries = 3;
    public static final int PLANNING_LINESMANMODE_NO_ELEVATOR = 0x1;//不使用电梯
    public static final int PLANNING_LINESMANMODE_NO_STAIRWAY = 0x0;//不使用楼梯
    public static final int PLANNING_LINESMANMODE_DEFAUIT = 0x2;// 默认
    private RequestQueue requestQueue;
    private static final String WIFI_RESULT_REQUEST_TAG = "wifi_result_request_tag";
    private static final String PLANNINGLINESMAN_REQUEST_TAG = "planninglinesman_request_tag";
    private static final String POISEARCH_REQUEST_TAG = "poisearch_request_tag";
    private String appKey;
    private String planningLinesmanUrl;
    private int dbm = 0; // 设备信号强度


    private boolean locationThreadStart = false;
    private List<Thread> locationThreadList;
    private int ratesTime;
    private coreAlgorithm coreAlgo;
    private String url = "http://106.2.180.42:9090";
    private int color;
    private long locationFloorId = -1;

    //    private String url = "http://192.168.199.229:8080";
    //    private List<Thread> runningThreads;
    private NexdLocationAgent() {
        collectionAgent = NexdCollectionAgent.getInstance();
        collectorConfig = new CollectorConfig.Builder();
        collectorConfig.setSensorEnable(false);
        collectorConfig.setBluetoothEnable(true);
        collectorConfig.setCollectorDelay(1500);
        collectorConfig.setCollectionMode(Collector.COLLECTION_MODE_ACTIVE);
        locationThreadList = new ArrayList<>();
        //        runningThreads = new ArrayList<>();

        this.coreAlgo = new coreAlgorithm();


    }


    /**
     * 设置配置文件
     *
     * @param parentPath 父级目录
     * @param configName 文件名称
     */
    public void setLocationConfig(final String parentPath, final String configName) {
        Runtime.getRuntime().gc();
//        coreAlgo = new coreAlgorithm()'''

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.i(NexdLocationAgent.this.getClass().getSimpleName(), "配置文件： " + configName);
                    InputStream opt = new FileInputStream(new File(parentPath + File.separator + configName + ".optparam"));
                    InputStream wifilist = new FileInputStream(new File(parentPath + File.separator + configName + ".wifilist"));
                    InputStream wp = new FileInputStream(new File(parentPath + File.separator + configName + ".wp"));
                    coreAlgo.initSet(opt, wp, wifilist);
                    String floorName = configName.substring(0, configName.length() - 4);
                    Log.d("FloorNameMiao", floorName);
                    InputStream mean = new FileInputStream(new File(parentPath + File.separator + floorName + ".mean"));
                    InputStream var = new FileInputStream(new File(parentPath + File.separator + floorName + ".var"));
                    InputStream weight = new FileInputStream(new File(parentPath + File.separator + floorName + ".weight"));
                    InputStream floor_wifilist = new FileInputStream(new File(parentPath + File.separator + floorName + ".wifilist"));
                    coreAlgo.floorSet(mean, var, weight, floor_wifilist);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }


    public void setNexdLocationSignalListener(NexdLocationSignalListener nexdLocationSignalListener) {
        this.nexdLocationSignalListener = nexdLocationSignalListener;
    }

    /**
     * 设置地图显示文字大小
     *
     * @param textSize 文字大小
     */
    public void setTextSize(int textSize) {
        BitmapUtils.TEXTSIZE = textSize;
    }

    /**
     * 设置配置文件
     *
     * @param configName
     */
    public void setLocationConfig(final Context context, final String configNameForLocation, final String configNameForFloor) {
        Runtime.getRuntime().gc();
//        coreAlgo = new coreAlgorithm();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.i(NexdLocationAgent.this.getClass().getSimpleName(), "定位文件: " + configNameForLocation + "\n 配置文件：" + configNameForFloor);
                    if (configNameForLocation != null) {
                        InputStream opt = context.getAssets().open(configNameForLocation + ".optparam");
                        InputStream wifilist = context.getAssets().open(configNameForLocation + ".wifilist");
                        InputStream wp = context.getAssets().open(configNameForLocation + ".wp");
                        coreAlgo.initSet(opt, wp, wifilist);
                    }

                    if (configNameForFloor != null) {
                        setLocationConfigForFloor(context, configNameForFloor);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

    private void setLocationConfigForFloor(Context context, String configName) throws IOException {

        InputStream mean = context.getAssets().open(configName + ".mean");
        InputStream var = context.getAssets().open(configName + ".var");
        InputStream weight = context.getAssets().open(configName + ".weight");
        InputStream floor_wifilist = context.getAssets().open(configName + ".wifilist");
        coreAlgo.floorSet(mean, var, weight, floor_wifilist);
    }

    public void setAppkey(String appKey) {
        this.appKey = appKey;
    }

    /**
     * 单例类，返回当前对象实例。
     */
    public static NexdLocationAgent getLocationAgent() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 向 SDK 中设置 Context 对象。强烈建议在获取当前对象之后调用此方法。
     *
     * @param context 当前上下文对象
     */
    public void setContext(Context context) {
        collectionAgent.setContext(context);
        this.context = context;
        requestQueue = Volley.newRequestQueue(context);
//        new DefaultRetryPolicy();
                        /*
        Get Input Stream From Assets to load configurations
         */

    }


    /**
     * http://192.168.199.228:8080/lenovo/api/poi2poi.do
     */
    public void setUrl(String url) {

        this.url = url;
    }

    /**
     * 开启一次定位, 通过使用 setLocationListener 接收定位结果
     *
     * @param ratesTime 定位频率
     */
    public void startLocation(int ratesTime) {
        locationFloorId = -1;
        this.startLocation(true, false, ratesTime);
//        this.startLocation(false, true, ratesTime);
    }

    public void startLocation(int ratesTime, long locationFloorId) {
        this.locationFloorId = locationFloorId;
        this.startLocation(true, false, ratesTime);
    }

    /**
     * 开启一次定位, 通过使用 setLocationListener 接收定位结果
     *
     * @param wifi      是否使用 wifi
     * @param beacon    是否使用 beacon
     * @param ratesTime 定位频率
     */
    private void startLocation(final boolean wifi, boolean beacon, int ratesTime) {
        this.ratesTime = ratesTime;
        collectorConfig.setWifiEnable(wifi);
        if (nexdLocationSignalListener != null) {
            collectorConfig.setBasebandEnable(wifi);
        }
        collectorConfig.setBluetoothEnable(beacon);
        collectorConfig.setWifiDelay(ratesTime, ratesTime);
        collectorConfig.setBluetoothDelay(ratesTime);

        try {
            if (wifi) {
                collectionAgent.setBasebandCollectorResultListener(new BasebandCollectorResultListener() {
                    @Override
                    public void onSuccess(String scanId, BasebandDataResult basebandDataResult) {
//                        Log.d("CellPhoneCollector", "##SUCCESS## " + basebandDataResult.toString());
                        dbm = basebandDataResult.getSignalStrength();
                    }

                    @Override
                    public void onFailed(String scanId, int faied_id, String message) {
//                        Log.e("CellPhoneCollector", message);
                    }
                });

                collectionAgent.setWifiCollectorResultListener(new WifiCollectorResultListener() {
                    @Override
                    public void onSuccess(String scanId, List<WifiDataResult> wifiDataResults) {
                        // 先定位所在楼层，然后调用定位业务，生成定位坐标，并通过 loacationListener回调定位结果.
                        //                    locationListener.onLocationSuccess(new PointF(100, 300), 0000, "");
                        //                    NexdCollectionAsyncTask.executeAllowingLoss(new Loacation(scanId, wifiDataResults));
                        //                    NexdCollectionAsyncTask.execute(new Loacation(scanId, wifiDataResults));
                        if (wifiDataResults != null && wifiDataResults.size() != 0) {
                            if (nexdLocationSignalListener != null) {
                                nexdLocationSignalListener.onLocationSuccess(wifiDataResults, dbm);
                            }
                        } else {
                            if (nexdLocationSignalListener != null) {
                                nexdLocationSignalListener.onLocationFailed("wifi采集信息为空");
                            }
                        }
                        //  输入平均处理
//                        List<WifiDataResult> avgWifiDataResult = WifiSignalHelper.getAvgWifiDataResult(wifiDataResults);
                        Log.d("onSuccess", "onSuccess");
//                        locationThreadList.add(new Loacation(scanId, avgWifiDataResult));
                        locationThreadList.add(new Loacation(scanId, wifiDataResults));
                        Thread runnable = locationThreadList.remove(locationThreadList.size() - 1);
                        NexdCollectionAsyncTask.execute(runnable);
                        //                    runningThreads.add(runnable);
                        if (locationThreadList.size() > 0 && !locationThreadStart) {
                            locationThreadStart = true;
                        }
                    }

                    @Override
                    public void onFailed(String scanId, int faied_id, String message) {
                        if (locationListener != null) {
                            locationListener.onLocationFailed(message);
                        }
                    }
                });
            }
        } catch (Exception e) {
        }
        if (beacon) {
            Log.d("BlueTooth", "准备注册蓝牙监听；");
            collectionAgent.setBluetoothCollectorResultListener(new BluetoothCollrctorResultListener() {
                @Override
                public void onSuccess(String scanId, List<BluetoothDataResult> bluetoothDataResults) {
                    // 调用定位业务，生成定位坐标，并通过 loacationListener回调定位结果
                    Log.i("BlueCollection", bluetoothDataResults.get(0).getAddress());
                    if (bluetoothDataResults != null) {
                        List<BluetoothDataResult> avgWifiDataResult = WifiSignalHelper.getAvgBlueDataResult(bluetoothDataResults);
                        locationThreadList.add(new Loacation(scanId, avgWifiDataResult, null));
                        Thread runnable = locationThreadList.remove(locationThreadList.size() - 1);
                        NexdCollectionAsyncTask.execute(runnable);
                        if (locationThreadList.size() > 0 && !locationThreadStart) {
                            locationThreadStart = true;
                        }
                    }
                }

                @Override
                public void onFailed(String scanId, int faied_id, String message) {
                    if (locationListener != null) {
                        locationListener.onLocationFailed(message);
                    }
                }
            });
        }

        collectionAgent.setCollectorConfig(collectorConfig.build());
        try {
            collectionAgent.startCollection();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 定位结果回调。用于定时将定位结果回调到前台。需要在startLocation之前调用.
     */
    public void setLocationListener(NexdLocationListener locationListener) {
        this.locationListener = locationListener;
    }

    /**
     * 停止定位
     */
    public void stopLocation() {
        locationFloorId = -1;
        collectionAgent.stopCollection();
        requestQueue.cancelAll(PLANNINGLINESMAN_REQUEST_TAG);
        requestQueue.cancelAll(POISEARCH_REQUEST_TAG);
        requestQueue.cancelAll(WIFI_RESULT_REQUEST_TAG);
        locationThreadList.clear();
        collectionAgent.setWifiCollectorResultListener(null);
//        coreAlgo = null;
        //        if (runningThreads.size() > 0) {
        //            for (Thread runnable : runningThreads) {
        ////                runnable.interrupted();
        //                runnable.destroy();
        //            }
        //            runningThreads.clear();
        //        }
//        locationListener = null;
    }


    /**
     * 销毁当前实例
     */
    public void destory() {
        collectionAgent.destory();

        context = null;
        locationListener = null;
        collectorConfig = null;
        collectionAgent = null;
        requestQueue = null;
        appKey = "";
        planningLinesmanUrl = "";
        locationThreadList = null;
        coreAlgo = null;

        SingletonHolder.INSTANCE = null;

    }


    /**
     * 设置路径规划的规则，默认、不使用楼梯、不使用电梯
     * <p/>
     * 0：电梯优先 1：楼梯优先
     */
    public void setPlanningLinesmanMode(int planningLinesmanMode) {
        this.planningLinesmanMode = planningLinesmanMode;
    }

    //    URL:lenovo/v1.2/collection/initiative/wifi.nexd

    //    public void setPlanningLinesmanUrl(String planningLinesmanUrl) {
    //        this.planningLinesmanUrl = planningLinesmanUrl;
    //    }

    //    URL:lenovo/v1.2/collection/initiative/wifi.nexd

    //    public void setPlanningLinesmanUrl(String planningLinesmanUrl) {
    //        this.planningLinesmanUrl = planningLinesmanUrl;
    //    }

    /**
     * 路径规划。用于规划 poi 点之间的导航路径。POI_POI
     * <p/>
     * POIData 说明
     * <p/>
     * branch:所在园区，null \n
     * floorId:楼层 ID \n
     * pointF: PointF 对象 \n
     * distance:距离 ，null \n
     * poiType: POI 类型  0：电梯 1：楼梯
     */
    public void planningLinesman(POIData startPoi, POIData endPoi, final NexdPlanningLiesmanListener planningLiesmanListener) {
        // 返回一个默认值

        StringBuilder url = new StringBuilder();

        url.append(this.url).append("/lenovo/api/poi2poi.do").append("?").append("appKey").append("=").append(appKey == null ? "" : appKey).append("&").
                //                append("floorId").append("=").append(floorId).append("&").
                        append("startPoiId").append("=").append(startPoi.getPoi_id()).append("&").
                append("endPoiId").append("=").append(endPoi.getPoi_id()).append("&").
                append("mode").append("=").append(planningLinesmanMode);
        Log.d("POI_POI", url);
        requestPlanningLinesman(planningLiesmanListener, url);

    }


    private void requestPlanningLinesman(final NexdPlanningLiesmanListener planningLiesmanListener, StringBuilder url) {

        if (planningLiesmanListener != null) {
            planningLiesmanListener.onPlanningLiesmanStarting();
        }
        StringRequest planningLinesmanRequest = new StringRequest(Request.Method.POST, url.toString(), new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.d("planningLinesman", "@@" + response);
                if (!TextUtils.isEmpty(response)) {
                    Map<String, Object> map = new JsonParseUtil().parse(response);
                    if (map != null) {

                        if ((boolean) map.get("isSuccess")) {

                            //                            Map<String, Object> data = (Map<String, Object>) map.get("result");
                            List<Map<String, Object>> list = (List<Map<String, Object>>) map.get("results");

                            long startFloorId = -1L;
                            long endFloorId = -1L;
                            final PlanningLiesmanData planningLiesmanData = new PlanningLiesmanData();

                            List<PointData> pointDatas = new ArrayList<>();

                            for (int i = 0, len = list.size(); i < len; i++) {
                                Map<String, Object> result_map = list.get(i);
                                PointData pointData = new PointData();

                                if (i == 0) {
                                    //                                    startFloorId = Long.parseLong(TextUtils.isEmpty((String) result_map.get("floorId")) ? "-1" : (String) result_map.get("floorId"));
                                    String startId = (String) result_map.get("floorId");
                                    startFloorId = Long.parseLong(TextUtils.isEmpty(startId) ? "-1" : startId);
                                    //                                    Log.e("===================================", String.valueOf(startFloorId));
                                }

                                if (i == len - 1) {
                                    String endId = (String) result_map.get("floorId");
                                    endFloorId = Long.parseLong(TextUtils.isEmpty(endId) ? "-1" : endId);
                                }
                                pointData.setPointF(new PointF(Float.parseFloat(TextUtils.isEmpty((String) result_map.get("x")) ? "-1" :
                                        (String) result_map.get("x")),
                                        Float.parseFloat(TextUtils.isEmpty((String) result_map.get("y")) ? "-1" : (String) result_map.get("y"))))
                                ;
                                pointData.setDistance(Float.parseFloat(TextUtils.isEmpty((String) result_map.get("distance")) ? "-1" : (String) result_map.get("distance")));
                                pointData.setBranch(TextUtils.isEmpty((String) result_map.get("branch")) ? "" : (String) result_map.get("branch"));
                                String floorId = (String) result_map.get("floorId");
                                pointData.setFloorId(Long.parseLong(TextUtils.isEmpty(floorId) ? "-1" : floorId));
                                pointData.setPoiType(Integer.parseInt((String) result_map.get("poitype")));
                                String buidingString = (String) result_map.get("buildingId");
                                pointData.setBuildingId(Long.parseLong(TextUtils.isEmpty(buidingString) ? "-1" : buidingString));
                                pointDatas.add(pointData);
                            }

                            planningLiesmanData.setStartFloorId(startFloorId);
                            planningLiesmanData.setEndFloorId(endFloorId);
                            planningLiesmanData.setPointDatas(pointDatas);


                            if (startFloorId != -1L) {
                                if (planningLiesmanListener != null) {
                                    ((Activity) context).runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            planningLiesmanListener.onPlanningLiesmanSuccess(planningLiesmanData);

                                        }
                                    });
                                } else {
                                    ((Activity) context).runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            planningLiesmanListener.onPlanningLiesmanFailed("result is null");
                                        }
                                    });
                                }
                            } else {
                                if (planningLiesmanListener != null) {
                                    ((Activity) context).runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            planningLiesmanListener.onPlanningLiesmanFailed("result is null");
                                        }
                                    });
                                } else {
                                    ((Activity) context).runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            planningLiesmanListener.onPlanningLiesmanFailed("result is null");
                                        }
                                    });
                                }
                            }
                        } else {

                            if (planningLiesmanListener != null) {
                                ((Activity) context).runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        planningLiesmanListener.onPlanningLiesmanFailed("请求失败");
                                    }
                                });
                            }
                        }


                    } else {

                        if (planningLiesmanListener != null) {
                            ((Activity) context).runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    planningLiesmanListener.onPlanningLiesmanFailed("JSON 不合法");
                                }
                            });
                        }
                    }
                } else {
                    if (planningLiesmanListener != null) {
                        ((Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                planningLiesmanListener.onPlanningLiesmanFailed("result is null");
                            }
                        });
                    }

                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(final VolleyError error) {

                if (planningLiesmanListener != null) {
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            planningLiesmanListener.onPlanningLiesmanFailed(error.getMessage());
                        }
                    });
                }
            }
        });
        planningLinesmanRequest.setRetryPolicy(new DefaultRetryPolicy(timeout * 1000, retries, 1.0f));
        planningLinesmanRequest.setTag(PLANNINGLINESMAN_REQUEST_TAG);
        requestQueue.add(planningLinesmanRequest);
    }

    /**
     * 设置http请求超时时间
     *
     * @param timeout
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * 设置http请求重试次数
     *
     * @param retries
     */
    public void setRetries(int retries) {
        this.retries = retries;
    }


    /**
     * 路径规划。用于规划 坐标点到 POI 点之间的导航路径。xy_POI
     */
    public void planningLinesman(long floorId, float x, float y, POIData endPoi, final NexdPlanningLiesmanListener planningLiesmanListener) {
        StringBuilder url = new StringBuilder();
        url.append(this.url).append("/lenovo/api/coordinate2poi.do").append("?").append("appKey").append(appKey == null ? "" : appKey).append("&")
                .append("startX").append("=").append(x).append("&")
                .append("startY").append("=").append(y).append("&")
                .append("floorId").append("=").append(floorId).append("&")
                .append("endPoiId").append("=").append(endPoi.getPoi_id()).append("&")
                .append("mode").append("=").append(planningLinesmanMode);
        requestPlanningLinesman(planningLiesmanListener, url);
    }

    public void poiSearch(long currrentFloorId, int poiType, int scope, float x, float y, final POISearchListener poiSearchListener, SVGMapView mapView) {
        List<POIData> poiDatas = mapView.poiSearch(poiType, x, y);
        poiSearchListener.onSearchStart();
        if (poiDatas != null) {
            poiSearchListener.onSearchSuccess(poiDatas);
        } else {
            poiSearchListener.onSearchFailed("搜索失败");
        }
    }

    /**
     * @param svgMapView 当前地图对象
     * @return FloorsFeature 楼层全部信息
     */
    public FloorsFeature getFloorsFeature(SVGMapView svgMapView) {
        return svgMapView.getFloorFeature();
    }

    /**
     * poi搜索。搜索特定范围内的 POI 信息。
     *
     * @param poiType POI类型
     * @param scope   范围（米）
     */
    public void poiSearch(float x, float y, long currrentFloorId, int poiType, int scope, final POISearchListener poiSearchListener) {
        // 将整栋楼的路网信息加载进来之后，查询需要的 POI
        if (poiSearchListener != null) {
            poiSearchListener.onSearchStart();
        }

        StringBuilder builder = new StringBuilder();
        builder.append(this.url).append("/lenovo/api/searchPoi.do").append("?appKey=").append(appKey == null ? "" : appKey).append("&floorId=").append(currrentFloorId).append("&currentX=").append(x)
                .append("&currentY=").append(y).append("&scope=").append(scope).append("&spaceId=").append(poiType);
        Log.d("searchPoi", builder.toString());
        StringRequest poiSearchRequest = new StringRequest(Request.Method.POST, builder.toString(), new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.d("httpRequest", response);
                Map<String, Object> map = new JsonParseUtil().parse(response);

                if ((boolean) map.get("isSuccess")) {
                    List<Map<String, Object>> results = (List<Map<String, Object>>) map.get("results");

                    final List<POIData> poiDataList = new ArrayList<>();
                    for (Map<String, Object> result : results) {
                        POIData poiData = new POIData();
                        poiData.setFloor_id(-1L);
                        poiData.setLocation("");
                        poiData.setFloor("");

                        poiData.setSpaceType(Integer.parseInt((String) result.get("spaceId")));
                        poiData.setPoi_id(Long.parseLong((String) result.get("poiId")));
                        poiData.setCenter_x(Float.parseFloat((String) result.get("currentX")));
                        poiData.setCenter_y(Float.parseFloat((String) result.get("currentY")));
                        poiData.setDistance(Float.parseFloat((String) result.get("dist")));

                        poiData.setName("");
                        poiData.setUrl("");

                        poiDataList.add(poiData);
                    }

                    if (poiSearchListener != null) {
                        ((Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                poiSearchListener.onSearchSuccess(poiDataList);
                            }
                        });
                    }
                } else {

                    if (poiSearchListener != null) {
                        ((Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                poiSearchListener.onSearchFailed("网络错误");

                            }
                        });
                    }
                }


            }
        }

                , new Response.ErrorListener()

        {
            @Override
            public void onErrorResponse(final VolleyError error) {
//                Log.d("httpRequest", error.getMessage() + "" + "\n" +"statusCode == " + error.networkResponse.statusCode);
                if (poiSearchListener != null) {
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            poiSearchListener.onSearchFailed(error.getMessage());
                        }
                    });
                }

            }
        }

        );
        poiSearchRequest.setRetryPolicy(new DefaultRetryPolicy(timeout * 1000, retries, 1.0f));
        poiSearchRequest.setTag(POISEARCH_REQUEST_TAG);
        requestQueue.add(poiSearchRequest);
    }

    public void setHightLightColor(int color) {
        this.color = color;
        BitmapUtils.color = color;
    }

    public void setShowTextSize(int size) {
        BitmapUtils.SHOWTEXTSIZE = size;
    }

    public void setIsHightLight(boolean hightLight) {
        BitmapUtils.hightLight = hightLight;
    }

    private class Loacation extends Thread {
        private String scanId;
        private List<WifiDataResult> wifiDataResults;
        private List<BluetoothDataResult> bluetoothDataResults;
        private String floorId = "-1";
        private String x = "-1";
        private String y = "-1";

        public Loacation(String scanId, List<WifiDataResult> wifiDataResults) {
            this.scanId = scanId;
            this.wifiDataResults = wifiDataResults;
        }

        public Loacation(String scanId, List<BluetoothDataResult> bluetoothDataResults, List<WifiDataResult> wifiDataResults) {
            this.scanId = scanId;
            this.bluetoothDataResults = bluetoothDataResults;
            this.wifiDataResults = wifiDataResults;
        }

        @Override
        public void run() {
            //定位业务运行在这里，
            // 首先调用晓龙的定位算法，获得坐标。
            // 根据返回值解析出定位结果

            //            Log.d("Loacation", "Loacation start");

            if (locationListener != null) {
                ((Activity) context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (locationListener != null) {
                            locationListener.onLocationStart();
                        }
                    }
                });
            }
            String locationResult = "";

            if (wifiDataResults != null && wifiDataResults.size() != 0) {
                locationResult = this.onLocationThread(wifiDataResults);
            } else if (bluetoothDataResults != null && wifiDataResults == null) {
                locationResult = this.onLocationThreadBlueTooth(bluetoothDataResults);
            }

            Log.d("locationResult", "## " + locationResult);
            if (!TextUtils.isEmpty(locationResult)) {
                // 不为空，定位成功
                // 定位数据格式{"floor_id":"101010100110","y":"125.234234","x":"48.2323"}
                try {
                    JSONObject jsonObject = new JSONObject(locationResult);
                    floorId = jsonObject.getString("floor_id") == null ? "-1" : jsonObject.getString("floor_id");
                    x = jsonObject.getString("x") == null ? "-1" : jsonObject.getString("x");
                    y = jsonObject.getString("y") == null ? "-1" : jsonObject.getString("y");


                    if ((floorId.equals("-1")) && locationListener != null) {
                        // 定位失败
                        ((Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (locationListener != null) {
                                    locationListener.onLocationFailed("定位失败");
                                }
                            }
                        });
                    } else {
                        if (x.equals("-1") || y.equals("-1")) {
                            // 定位楼层成功，定位坐标失败

                            if (locationListener != null) {
                                ((Activity) context).runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        if (locationListener != null) {
                                            if (locationFloorId == -1) {
                                                locationListener.onLocationSuccess(null, floorId);
                                            } else {
                                                locationListener.onLocationSuccess(null, String.valueOf(locationFloorId));
                                            }
                                        }
                                    }
                                });
                            }
                        } else {
                            // 楼层坐标都成功
                            final PointF pointF = new PointF(Float.parseFloat(x), Float.parseFloat(y));
                            if (locationListener != null) {
                                ((Activity) context).runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        if (locationListener != null) {
                                            if (locationFloorId == -1) {
                                                locationListener.onLocationSuccess(pointF, floorId);
                                            } else {
                                                locationListener.onLocationSuccess(pointF, String.valueOf(locationFloorId));
                                            }
                                        }
                                    }
                                });
                            }
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            } else {
                // 没有定位结果，定位失败
                if (locationListener != null) {
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (locationListener != null) {
                                    locationListener.onLocationFailed("定位失败");
                                }
                            } catch (NullPointerException e) {
                                Log.e(this.getClass().getSimpleName(), "已停止定位");
                                e.printStackTrace();
                            }
                        }
                    });
                }
            }

            if (requestQueue != null) {
                // 提交数据到服务端
                ((Activity) context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                        Request postCollectorResultRequest = null;
                        if (wifiDataResults != null) {
                            postCollectorResultRequest = new PostWifiCollectorResult(scanId, floorId, x, y, wifiDataResults, new DefaultResponseListener(), new DefaultErrorListener());
                            postCollectorResultRequest.setTag(WIFI_RESULT_REQUEST_TAG);
                            requestQueue.add(postCollectorResultRequest);
                        } else if (bluetoothDataResults != null) {
                            // TODO 这里是否添加蓝牙数据上传任务
//                            postCollectorResultRequest = new Post
                        }

                    }
                });
            }

            try {
                Thread.sleep(ratesTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            if (locationThreadList.size() > 0) {
                TaskExecutor.startAllowingLoss(locationThreadList.remove(locationThreadList.size() - 1));
            } else {
                locationThreadStart = false;
            }

            //            if (runningThreads.size() > 0) {
            //                runningThreads.remove(0);
            //            }
        }

        private String onLocationThreadBlueTooth(List<BluetoothDataResult> bluetoothDataResults) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("{");
//            stringBuilder.append("\"").append(bluetoothDataResult.getAddress()).append("\"").append(":").append("\"").append(bluetoothDataResult.getRssi()).append("\"");
            for (int i = 0, len = bluetoothDataResults.size(); i < len; i++) {
                BluetoothDataResult bluetoothDataResult = bluetoothDataResults.get(i);
                stringBuilder.append("\n\t\t\"").append(bluetoothDataResult.getAddress()).append("\"").append(":").append("\"").append(bluetoothDataResult.getRssi()).append("\"");
                if (i < len - 1) {
                    stringBuilder.append(",");
                }
            }
            stringBuilder.append("}");

            Log.d("BlueToothData", stringBuilder.toString());

            String result = "";
            try {
                result = coreAlgo.locateOutput(stringBuilder.toString());

            } catch (JSONException e) {
                result = "";
            }

            return result;
        }

        private String onLocationThread(List<WifiDataResult> wifiDataResults) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("{");

            for (int i = 0, len = wifiDataResults.size(); i < len; i++) {
                WifiDataResult wifiDataResult = wifiDataResults.get(i);
                stringBuilder.append("\n\t\t\"").append(wifiDataResult.getBssid()).append("\"").append(":").append("\"").append(Integer.toString(wifiDataResult.getLevel())).append("\"");
                if (i < len - 1) {
                    stringBuilder.append(",");
                }
            }
            stringBuilder.append("}");

            Log.d("wifi", " " + wifiDataResults.size());
            Log.d("onLocationThread", "" + stringBuilder.toString());
            // 定位数据是 stringBuilder
            // 以下是定位业务

            //            Log.d("onLocationThread", "" + stringBuilder.toString());
            Log.d("onLocationThread", "Calling");
            // 定位数据是 stringBuilder
            String floor_id = "101001040002";//Beijing APM F1

            String res;

            //            Log.d("onNBClassifier","" + locationGenerator.clf.post_mean.length);
            //            Log.d("LocationResult", "Location Service Started");

            long startTime = System.currentTimeMillis();
            try {
                //                res = locationGenerator.locatePosition(stringBuilder.toString(), floor_id);
                //                res = coreAlgo.locateOutput(stringBuilder.toString(), floor_id);


                res = coreAlgo.locateOutput(stringBuilder.toString());
                //                res = coreAlgo.locateOutput(wifiSample);

            } catch (JSONException e) {
                res = "";
                //                e.printStackTrace();
            } catch (NullPointerException e) {
                res = "";
                //                e.printStackTrace();
            } catch (ArrayIndexOutOfBoundsException e) {
                res = "";
                //                e.printStackTrace();
            } catch (Exception e) {
                res = "";
            }

            //            catch (Exception e) {
            //                res = "";
            //                e.printStackTrace();
            //            }
            long endTime = System.currentTimeMillis();
            //            Log.d("LocationResult","Result "+ res);
            Log.d("onLocationThreadTime", "Location Agent Time Comsumption   " + (endTime - startTime));

            return res;
        }
    }

    private static class SingletonHolder {
        private static NexdLocationAgent INSTANCE = new NexdLocationAgent();
    }

    //    private void copyBigDataToSD(String strOutFileName, String intPutName) throws IOException {
    //
    //        File file = new File(strOutFileName);
    //
    //        if (file.exists()) {
    //            file.delete();
    //        }
    //        InputStream myInput;
    //        OutputStream myOutput = new FileOutputStream(strOutFileName);
    //        myInput = context.getAssets().open(intPutName);
    //        byte[] buffer = new byte[1024];
    //        int length = myInput.read(buffer);
    //
    //        while (length > 0) {
    //            myOutput.write(buffer, 0, length);
    //            length = myInput.read(buffer);
    //        }
    //
    //        myOutput.flush();
    //        myInput.close();
    //        myOutput.close();
    //    }


    private class PostWifiCollectorResult extends Request<String> {
        private Response.Listener<String> mListener;
        private String scanId;
        private String floorId;
        private String x;
        private String y;
        private List<WifiDataResult> wifiDataResults;
        private DefaultResponseListener defaultResponseListener = new DefaultResponseListener();


        public PostWifiCollectorResult(String scanId, String floorId, String x, String y, List<WifiDataResult> wifiDataResults, Response.Listener<String> listener, Response.ErrorListener errorListener) {

            this("http://api.nexd.com/lenovo/v1.2/collection/initiative/wifi.do", listener, errorListener);
            this.scanId = scanId;
            this.floorId = floorId;
            this.x = x;
            this.y = y;
            this.wifiDataResults = wifiDataResults;
        }

        public PostWifiCollectorResult(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
            super(method, url, errorListener);
            this.mListener = listener;

        }


        public PostWifiCollectorResult(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
            this(Method.POST, url, listener, errorListener);
        }


        @Override
        protected Map<String, String> getParams() throws AuthFailureError {

            StringBuilder dataStringBuilder = new StringBuilder();
            dataStringBuilder.append("[");

            for (int i = 0, len = wifiDataResults.size(); i < len; i++) {
                WifiDataResult wifiDataResult = wifiDataResults.get(i);
                dataStringBuilder.append("{").append("appKey").append(":'").append(appKey == null ? "" : appKey).append("',");
                dataStringBuilder.append("singleintensity").append(":").append(wifiDataResult.getSingleIntensity()).append(",");
                dataStringBuilder.append("timestamp").append(":").append(wifiDataResult.getTimestamp()).append(",");
                dataStringBuilder.append("ssid").append(":'").append(wifiDataResult.getSsid()).append("',");
                dataStringBuilder.append("capability").append(":'").append(wifiDataResult.getCapability()).append("',");
                dataStringBuilder.append("bssid").append(":'").append(wifiDataResult.getBssid()).append("',");
                dataStringBuilder.append("scanId").append(":'").append(scanId).append("',");
                dataStringBuilder.append("frequency").append(":").append(wifiDataResult.getFrequency()).append(",");
                dataStringBuilder.append("level").append(":").append(wifiDataResult.getLevel());
                dataStringBuilder.append("}");

                if (i < len - 1) {
                    dataStringBuilder.append(",");
                }
            }

            dataStringBuilder.append("]");

            StringBuilder resultStringBuilder = new StringBuilder();
            resultStringBuilder.append("[").append("{");
            resultStringBuilder.append("appKey").append(":").append(appKey).append(",");
            resultStringBuilder.append("post_x").append(":").append(x).append(",");
            resultStringBuilder.append("post_y").append(":").append(y).append(",");
            resultStringBuilder.append("floor").append(":").append(floorId).append(",");
            resultStringBuilder.append("scanId").append(":").append(scanId);
            resultStringBuilder.append("}");
            resultStringBuilder.append("]");

            Map<String, String> map = new HashMap<>();
            map.put("data", dataStringBuilder.toString());
            map.put("result", resultStringBuilder.toString());

            return map;
        }

        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse response) {
            String parsed;
            try {
                parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            } catch (UnsupportedEncodingException e) {
                parsed = new String(response.data);
            }
            return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
        }

        @Override
        protected void deliverResponse(String response) {
            mListener.onResponse(response);
        }
    }


    private class DefaultResponseListener implements Response.Listener<String> {

        @Override
        public void onResponse(String response) {
            Log.d("DefaultResponseListener", "" + response);
        }
    }

    private class DefaultErrorListener implements Response.ErrorListener {

        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("DefaultResponseListener", "" + error.getMessage());
        }
    }

    /**
     * 返回楼层 ID 与楼层名称对应的列表.(目前为 null，等待数据)
     */
    private Floors getFloors() {
        try {
            return FloorsUtils.getFloorsUtils().getFloors(context.getAssets().open(""));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}
